package com.bsj.power.pls.queue.service.impl.handle;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bsj.consumerQ.function.HandleRunT;
import com.bsj.power.common.config.cached.RedisCached;
import com.bsj.power.common.config.redis.AlarmConstant;
import com.bsj.power.common.config.redis.RedisConstant;
import com.bsj.power.common.config.rocketmq.producer.BaseMqPushUtil;
import com.bsj.power.common.constant.MqTopicAndTagConstants;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.def.dto.AlarmCombinationRDS;
import com.bsj.power.common.def.entity.alarmReport.AlarmReport;
import com.bsj.power.common.def.entity.sys.SystemConfig;
import com.bsj.power.common.def.vo.WebSocketMsgVO;
import com.bsj.power.common.mapper.AlarmReportMapper;
import com.bsj.power.common.util.ExceptionUtil;
import com.bsj.power.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.bsj.JedisClusterBSJ;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yinhao
 * @version 1.0
 * @description 组合报警处理类
 * @date 2024/9/26
 */
@Slf4j
@Service
public class QueueComposeAlarmHandle implements HandleRunT<Object> {

    @Autowired
    private RedisCached redisCached;

    @Autowired
    private JedisClusterBSJ jedisClusterBSJ;

    @Autowired
    private BaseMqPushUtil baseMqPushUtil;

    @Resource
    private AlarmReportMapper alarmReportMapper;

    @Override
    public void doRun(List<Object> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        try {
            String confStr = redisCached.get(RedisConstant.SYS_CONF_MODE);
            if (StringUtils.isEmpty(confStr)) {
                log.warn("组合报警处理类未获取到全局配置项信息!");
                return;
            }
            //规则配置内容
            SystemConfig systemConfig = JSONObject.parseObject(confStr, SystemConfig.class);
            Integer composeAlarmTime = systemConfig.getComposeAlarmTime();
            if (composeAlarmTime == null) {
                log.warn("组合报警处理类未获取到时长: {}", confStr);
                return;
            }
            //已设置的组合报警集合
            Map<String, String> alarmComb = redisCached.hgetAll(RedisConstant.ALARM_COMBINATION);
            if (CollectionUtil.isEmpty(alarmComb)) {
                log.warn("组合报警处理类未获取到组合报警设置信息");
                return;
            }
            Date date = new Date();
            List<AlarmReport> insertAlarmReport = new ArrayList<>();
            for (Object o : list) {
                if (o instanceof AlarmReport) {
                    //当前触发的报警信息
                    AlarmReport report = (AlarmReport) o;
                    //当前触发的报警类型
                    Integer alarmType = report.getAlarmType();
                    alarmComb.forEach((key, value) -> {
                        AlarmCombinationRDS combinationRDS = JSON.parseObject(value, AlarmCombinationRDS.class);
                        //组合报警状态码
                        String comCode = combinationRDS.getComCode();
                        List<Integer> comCodeList = Arrays.stream(comCode.split(","))
                                .map(Integer::parseInt).collect(Collectors.toList());
                        if (!comCodeList.contains(alarmType)) {
                            return;
                        }
                        //目前已经产生报警的状态集合
                        String combinationStr = jedisClusterBSJ.get(AlarmConstant.COMBINATION_ALARM_STATE + key);
                        List<Integer> alarmCodeList = null;
                        if (combinationStr == null) {
                            alarmCodeList = new LinkedList<>();
                            alarmCodeList.add(alarmType);
                        } else {
                            alarmCodeList = JSONObject.parseArray(combinationStr, Integer.class);
                            alarmCodeList.add(alarmType);
                        }
                        //判断是不是需要报警
                        boolean equalsResult = compareLists(comCodeList, alarmCodeList);
                        if (equalsResult) {
                            //产生组合报警
                            AlarmReport alarmReport = new AlarmReport();
                            alarmReport.setAlarmType(NumericalConstants.FIVE);
                            alarmReport.setDeviceType(0);
                            alarmReport.setBeginTime(date);
                            alarmReport.setEndTime(date);
                            alarmReport.setComAlarmName(combinationRDS.getComName());
                            insertAlarmReport.add(alarmReport);
                            //产生报警后需要清除缓存状态
                            jedisClusterBSJ.del(AlarmConstant.COMBINATION_ALARM_STATE + key);
                            WebSocketMsgVO webSocketMsgVO = WebSocketMsgVO.builder()
                                    .msgType(NumericalConstants.SIX)
                                    .obj(alarmReport)
                                    .build();
                            baseMqPushUtil.sendTopicBytes(MqTopicAndTagConstants.SYSTEM_WEB_SERVER_CHANGE_TOPIC,
                                    MqTopicAndTagConstants.SYSTEM_WEB_PRODUCT_CHANGE_TAG, JSON.toJSONBytes(webSocketMsgVO));
                        } else {
                            //不产生组合报警,但是需要记录当前的报警状态
                            int ttl = Math.toIntExact(jedisClusterBSJ.ttl(AlarmConstant.COMBINATION_ALARM_STATE + key));
                            if (ttl == -1 || combinationStr == null) {
                                ttl = composeAlarmTime;
                            }
                            //未产生报警则需要记录已经产生的报警状态值,重复的报警状态值只记录一次
                            redisCached.set(AlarmConstant.COMBINATION_ALARM_STATE + key,
                                    JSON.toJSONString(alarmCodeList.stream().distinct().collect(Collectors.toList())), ttl);
                        }
                    });
                }
            }
            try {
                if (!insertAlarmReport.isEmpty()) {
                    //报表存储
                    insertAlarmReport.stream().forEach(item -> {
                        alarmReportMapper.insert(item);
                    });
                }
            } catch (Exception e) {
                log.info("进出围栏报警存储错误: {}, 异常信息: {}", ExceptionUtil.getStackStr(e));
                return;
            }
        } catch (Exception e) {
            log.error("组合报警处理失败： {}", ExceptionUtil.getStackStr(e));
            return;
        }
    }

    /**
     * 查看两个list中的值是否相等，不考虑排序
     *
     * @param list1
     * @param list2
     * @return
     */
    public static boolean compareLists(List<Integer> list1, List<Integer> list2) {
        List<Integer> sortedList1 = list1.stream().sorted().collect(Collectors.toList());
        List<Integer> sortedList2 = list2.stream().sorted().collect(Collectors.toList());
        return sortedList1.equals(sortedList2);
    }

}
